#ifndef CAMERABASE_HPP
#define CAMERABASE_HPP

#include "fiocpp.hpp"

#define USEQT

#ifdef USEQT
#include "fioqt.hpp"
#else
#include "fiowin.hpp"
#endif
#include <opencv2/opencv.hpp>

class CameraBase
{
public:
    virtual bool read(cv::Mat &image)
    {
        return false;
    }

    virtual void release()
    {

    }

    virtual bool open(int mode)
    {
        return false;
    }

    static void SaveImg(std::string folder, const cv::Mat &image, std::string ext=".png")
    {
        std::string filename=TimeString(2)+ext;
        if(cv::imwrite(folder+filename,image))
        {
           std::cout<<"save "<<filename<<'\n'<<std::flush;
        }
        else
        {
           std::cout<<"fail to save "<<filename<<'\n'<<std::flush;
        }
    }


    void test(int mode, std::string folder=TimeString(2)+"/", int countdown=100, std::string winname="frame", std::string ext=".png")
    {
        if (!open(mode))
        {
            std::cerr<<"Error opening the camera\n";
            return;
        }

        cv::Mat m;
        int key=0;
        int count=countdown;
        cv::namedWindow(winname, cv::WINDOW_NORMAL);
        while(key!=27)
        {
            if(read(m))
            {
                cv::imshow(winname,m);
            }
            key=cv::waitKey(1);

            if(countdown>0)
            {
                std::cout<<count<<'\n'<<std::flush;
                if(count==0)
                {
                    SetFolder(folder);
                    SaveImg(folder,m,ext);
                    count=countdown;
                    continue;
                }
                count--;
                continue;
            }

            if(key=='c')
            {
                SetFolder(folder);
                SaveImg(folder,m,ext);
            }

        }
        release();
    }


     void Record(int mode, int fourcc=CV_FOURCC('M','J','P','G'), std::string ext=".avi")
     {
         if (!open(mode))
         {
             std::cerr<<"Error opening the camera\n";
             return;
         }

         std::string winname=TimeString(2);

         cv::VideoWriter vw;


         cv::Mat m;
         int key=0;
         cv::namedWindow(winname, cv::WINDOW_NORMAL);
         while(key!=27)
         {
             if(read(m))
             {
                 cv::imshow(winname,m);
                 if(!vw.isOpened())
                     vw.open(winname+ext,fourcc,30,m.size(),true);
                 vw.write(m);
             }
             key=cv::waitKey(1);

         }
         release();
         vw.release();
     }


     void Record2(int mode, int fourcc=CV_FOURCC('Y','U','V','9'), std::string ext=".avi")
     {
         if (!open(mode))
         {
             std::cerr<<"Error opening the camera\n";
             return;
         }

         std::string winname=TimeString(2);

         cv::Mat m;
         int key=0;
         cv::namedWindow(winname, cv::WINDOW_NORMAL);
         while(key!=27)
         {
             if(read(m))
             {
                 cv::imshow(winname,m);
             }
             key=cv::waitKey(1);
         }
         m.release();

         int n=400;
         std::vector<cv::Mat> ml(n,cv::Mat());

         for(size_t i=0;i<ml.size();i++)
         {
             read(ml[i]);
             std::cout<<i<<'\n'<<std::flush;
         }
         release();


         SetFolder(winname);
         cv::namedWindow(winname, cv::WINDOW_NORMAL);
         for(size_t i=0;i<ml.size();i++)
         {
             cv::imshow(winname,ml[i]);
             char buf[50];
             sprintf(buf,"%03d.png",i);
             cv::imwrite(winname+"/"+std::string(buf),ml[i]);
             cv::waitKey(30);
             ml[i].release();

         }

    #if 0
         cv::VideoWriter vw(winname+ext,fourcc,30,cv::Size(width,height),true);

         cv::namedWindow(winname, cv::WINDOW_NORMAL);
         for(size_t i=0;i<ml.size();i++)
         {
             cv::imshow(winname,ml[i]);
             cv::cvtColor(ml[i],m,CV_GRAY2BGR);
             vw.write(m);
             cv::waitKey(30);
             ml[i].release();

         }
         vw.release();
#endif
     }

     static void Play(std::string fileName)
     {
             cv::VideoCapture c(fileName);
             cv::Mat m;
             while(c.read(m))
             {
                 cv::imshow(fileName,m);
                 cv::waitKey(1);
             }
     }     

};

#endif // CAMERABASE_HPP

